package org.game.manager;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sojoys.artifact.manager.MessageManager;
import com.sojoys.artifact.tools.ToolError;
import com.sojoys.artifact.tools.ToolMap;
import com.xiaoleilu.hutool.util.MapUtil;
import org.base.BaseGoods;
import org.cache.GoodsCfgCache;
import org.cfg.DiscreteDataCfg;
import org.cfg.RoleCfg;
import org.cfg.RoomCfg;
import org.cfg.cache.DiscreteDataCfgCache;
import org.cfg.cache.RoleCfgCache;
import org.constant.*;
import org.error.GameErrorCode;
import org.game.constant.ElementCollectionConstant;
import org.game.db.bean.Player;
import org.game.db.bean.PlayerData;
import org.game.db.bean.Role;
import org.game.db.cache.PlayerCache;
import org.game.db.cache.RoleCache;
import org.game.db.vo.PlayerDataVO;
import org.game.db.vo.RoomVO;
import org.game.log.LogRole;
import org.game.log.builder.LogDsp;
import org.game.log.dsp.GoodsDsp;
import org.game.log.dsp.RoleDsp;
import org.game.module.itembo.ItemBO;
import org.game.module.rolebo.RoleBO;
import org.game.msgBuilder.RoleMsgBuilder;
import org.game.plugin.event.GameEvent;
import org.game.plugin.event.GameEventPlugin;
import org.game.protobuf.s2c.S2CItemMsg.ItemList;
import org.game.protobuf.s2c.S2CRoleMsg.RoleInfo;
import org.game.protobuf.s2c.S2CShareMsg.ChangeType;
import org.game.util.ProtoUnit;
import org.utils.CommonUtil;
import org.utils.TimeUtil;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author : DengYing
 * @CreateDate : 2017年8月23日 下午1:06:23
 * @Description ：精灵管理器
 */
public class RoleManager {
	private RoleManager() {
	}

	private static RoleManager ME = new RoleManager();

	public static RoleManager me() {
		return ME;
	}
	
	
	/**
	 * 激活精灵
	 * @param player
	 * @param cid
	 */
	public void activateRole(Player player,int cid){
		// 判断是否已激活改精灵
		Role role = RoleCache.me().getByCidPlayerId(cid, player.getId());
		if (role!=null) {
			return;
		}
		RoleCfg cfg = RoleCfgCache.me().getById(cid);
		// 暂未开放
		if (cfg==null || !cfg.getIsOpen()) {
			return;
		}
		boolean createPlayer = PlayerManager.me().isCreatePlayer();
//		int status = createPlayer ? RoleConstant.STATUS_USE : RoleConstant.STATUS_DEFAULT;
		// 可能创建角色就有2个精灵
		PlayerData playerData = player.getPlayerDatasFkPlayerId();
		int status = playerData.getPlayerDataProxy().getDiscreteVO().getObtainRoleStatus();
//		int status = RoleCache.me().getByPlayerId(player.getId()).isEmpty() ? RoleConstant.STATUS_USE : RoleConstant.STATUS_DEFAULT;
		// 解锁礼品
		List<Integer> unlockGiftList = Lists.newArrayList();
		// 解锁爱好
		List<Integer> unlockHobbyList = Lists.newArrayList();
		
		// 默认解锁礼品
		Map<Integer, Integer> giftMap = cfg.getGift();
		for (Entry<Integer, Integer> e : giftMap.entrySet()) {
			if (e.getValue()==0) {
				unlockGiftList.add(e.getKey());
			}
		} 
		// 默认解锁爱好
		Map<Integer, Integer> hobbyMap = cfg.getHobby();
		for (Entry<Integer, Integer> e : hobbyMap.entrySet()) {
			if (e.getValue()==0) {
				unlockHobbyList.add(e.getKey());
			}
		} 
		role = new Role(0L, cid, player.getId(), cfg.getFavor(), 60, status,unlockGiftList,unlockHobbyList,Lists.newArrayList(),Maps.newHashMap(), new Date(),0,true, Lists.newArrayList(),0,new Date());
		role.insert();
		
		if (status == RoleConstant.STATUS_USE) {
			playerData.getPlayerDataProxy().getDiscreteVO().setObtainRoleStatus(RoleConstant.STATUS_DEFAULT);
			playerData.update();
		}
		int defaultDressId = cfg.getRoleModel();
		BaseGoods defaultDress = GoodsCfgCache.me().get(defaultDressId);
		if (defaultDress!=null) {
			// 初始默认时装 & 穿戴在该精灵上
			ItemList.Builder itemChange = ItemList.newBuilder();
			
			LogDsp log = LogDsp.newBuilder(GoodsDsp.ACTIVATE_ROLE).targetTag(role.getCid());
			
			ItemManager.addSingleGoods(player, null, role,itemChange,log, defaultDress.getId());
			if (!createPlayer) {
				player.getPlayerProxy().sendMsg(MessageManager.me().create(ItemBO.getItems, ProtoUnit.toByte(itemChange.build())));				
			}
		}
		
		if (!createPlayer) {
			player.getPlayerProxy().getRoles().put(role.getId(), role);
			RoleInfo roleInfo = RoleMsgBuilder.createRoleInfo(ChangeType.ADD, role);
			player.getPlayerProxy().sendMsg(MessageManager.me().create(RoleBO.pushRole, ProtoUnit.toByte(roleInfo)));
		}

		ElementCollectManager.recordElement(player, ElementCollectionConstant.KEY_ROLE,role.getCid());
		LogRole.me().log(player.getId(), role.getCid(), 1, 1, LogDsp.newBuilder(RoleDsp.ACTIVATE));
	}
	/**
	 * 修改心情值
	 * @param role
	 */
	public void changeMood(Role role,int changeNum,LogDsp logDsp){
		if (changeNum==0) {
			return;
		}
		DiscreteDataCfg cfg = DiscreteDataCfgCache.me().getById(DiscreteDataID.ROLE_MOOD_FAVOR);
		Map<String, Integer> config = null;
		int changeFavor = 0;
		if (changeNum > 0) {
			config = ToolMap.getMap(DiscreteDataKey.CEILING, cfg.getData());
			int mood = ToolMap.getInt(DiscreteDataKey.MOOD, config);
			int ratio = ToolMap.getInt(DiscreteDataKey.RATIO, config);
			if (role.getMood() + changeNum > mood) {
				// 溢出的心情值
				changeFavor = (int) ((role.getMood() + changeNum - mood) * ( ratio / 10000.0d));
				role.setMood(mood);
			}else {
				role.setMood(role.getMood() + changeNum);
			}
		}else {
			config = ToolMap.getMap(DiscreteDataKey.FLOOR, cfg.getData());
			int mood = ToolMap.getInt(DiscreteDataKey.MOOD, config);
			int ratio = ToolMap.getInt(DiscreteDataKey.RATIO, config);
			if (role.getMood() < mood) {
				changeFavor = (int) ((changeNum) * (ratio / 10000.0d));
				role.setMood(Math.max(0, role.getMood() + changeNum));
			}else if (role.getMood() + changeNum < mood) {
				changeFavor = (int) ((mood - role.getMood() + changeNum) * ( ratio / 10000.0d));
				role.setMood(Math.max(0, role.getMood() + changeNum));
			}else {
				role.setMood(role.getMood() + changeNum);
			}
		}
		
		LogDsp cloneLogDsp = logDsp.clone();
		LogRole.me().log(role.getPlayerId(), role.getCid(), changeNum, role.getMood(), logDsp);
		
		// 修改好感度
		if (changeFavor!=0) {
			changeFavor(role, changeFavor,cloneLogDsp.addCourse("changeMood"));
		}
		
		RoleInfo.Builder builder = RoleInfo.newBuilder();
		builder.setCt(ChangeType.UPDATE);
		builder.setMood(role.getMood());
		builder.setId(Long.toString(role.getId()));
		builder.setCid(role.getCid());
		RoleInfo roleInfo = builder.build();
		Player player = PlayerCache.me().getById(role.getPlayerId());
		player.getPlayerProxy().sendMsg(MessageManager.me().create(RoleBO.pushRole, ProtoUnit.toByte(roleInfo)));
	}
	
	/**
	 * 修改好感度
	 * @param role
	 */
	public void changeFavor(Role role,int changeNum,LogDsp logDsp){
		// 如果好感度已达临界点 & 是加好感度操作
		if (role.isCriticalPoint() && changeNum > 0){
			return;
		}
		int nowFavor = role.getFavor();
		RoleCfg cfg = role.getRoleProxy().getConfig();
		int[] favorLevels = cfg.getFavorLevels();
		int nowLvl = 0, maxLvl = favorLevels.length-1 ;
		
		for (int i = favorLevels.length-1; i >= 0; i--){
			if (nowFavor >= favorLevels[i]) {
				nowLvl = i ;
				break;
			}
		}
		if (changeNum < 0) {
			// 扣除好感度，不能掉级
			role.setFavor(Math.max(nowFavor+changeNum, favorLevels[nowLvl]));
			role.setCriticalPoint(false);
		}else {
			// 已达最大好感度
			if (nowFavor >= favorLevels[maxLvl]) {
				return;
			}
			
			int nextLvl = Math.min(maxLvl,nowLvl+1);
			if (nowFavor+changeNum >= favorLevels[nextLvl]){
				role.setFavor(favorLevels[nextLvl]);
				role.setCriticalPoint(true);
			}else{
				role.setFavor(nowFavor+changeNum);
			}
		}

		role.update();
		
		LogRole.me().log(role.getPlayerId(), role.getCid(), changeNum, role.getFavor(), logDsp);
		
		RoleInfo.Builder builder = RoleInfo.newBuilder();
		builder.setCt(ChangeType.UPDATE);
		builder.setFavor(role.getFavor());
		builder.setId(Long.toString(role.getId()));
		builder.setCid(role.getCid());
		builder.setFavorCriticalPoint(role.isCriticalPoint());
		RoleInfo roleInfo = builder.build();
		Player player = PlayerCache.me().getById(role.getPlayerId());
		player.getPlayerProxy().sendMsg(MessageManager.me().create(RoleBO.pushRole, ProtoUnit.toByte(roleInfo)));
		
		Map<String, Object> in = Maps.newHashMap();
		in.put(EventConditionKey.CONDITION_TYPE, EventConditionType.ROLE_FAVOR);
		in.put(EventConditionKey.OLD_FAVOR, nowFavor);
		in.put(EventConditionKey.NOW_FAVOR, role.getFavor());
		in.put(EventConditionKey.ROLE_CID, cfg.getId());
		GameEventPlugin.syncSubmit(new GameEvent(player, EventType.ROLE_CHANGE,in));
	}

	/**
	 * 解锁礼品
	 * @param roleCid
	 * @param giftCid
	 */
	public static void unlockGift(Player player,int roleCid, int giftCid) {
		Role role = RoleCache.me().getByCidPlayerId(roleCid, player.getId());
		if (role==null) {
			return;
		}
		ToolError.isAndTrue(GameErrorCode.THIS_ROLE_NOT_FOND_GIFT, "精灵没有配置该礼品",!role.getRoleProxy().getConfig().getGift().containsKey(giftCid));
		if (role.getUnlockGift().contains(giftCid)){
			return;
		}
		role.getUnlockGift().add(giftCid);
		role.update();
		
//		UnlockGiftMsg.Builder builder = UnlockGiftMsg.newBuilder();
//		builder.addAllUnlockGift(role.getUnlockGiftList());
//		builder.setId(role.getId());
//		player.sendMsg(MessageManager.me().newMesssage(RoleBO.unlockGift, builder.build().toByteArray()));
		
		RoleInfo.Builder builder = RoleInfo.newBuilder();
		builder.setCt(ChangeType.UPDATE);
		builder.setId(Long.toString(role.getId()));
		builder.setCid(role.getCid());
		builder.addAllUnlockGift(role.getUnlockGift());
		RoleInfo roleInfo = builder.build();
		player.getPlayerProxy().sendMsg(MessageManager.me().create(RoleBO.pushRole, ProtoUnit.toByte(roleInfo)));
	}
	
	/**
	 * 解锁爱好
	 * @param roleCid
	 */
	public static void unlockHobby(Player player,int roleCid, int hobbyCid) {
		Role role = RoleCache.me().getByCidPlayerId(roleCid, player.getId());
		if (role==null) {
			return;
		}
		role.getUnlockHobby().add(hobbyCid);
		role.update();
		
//		UnlockHobbyMsg.Builder builder = UnlockHobbyMsg.newBuilder();
//		builder.addAllUnlockHobby(role.getUnlockHobbyList());
//		builder.setId(role.getId());
//		player.sendMsg(MessageManager.me().newMesssage(RoleBO.unlockHobby, builder.build().toByteArray()));
		RoleInfo.Builder builder = RoleInfo.newBuilder();
		builder.setCt(ChangeType.UPDATE);
		builder.setId(Long.toString(role.getId()));
		builder.setCid(role.getCid());
		builder.addAllUnlockHobby(role.getUnlockHobby());
		RoleInfo roleInfo = builder.build();
		player.getPlayerProxy().sendMsg(MessageManager.me().create(RoleBO.pushRole, ProtoUnit.toByte(roleInfo)));
	}

	/**
	 * 更换房间
	 * */
	public static List<Role> changeRoom(Role role, RoomVO room){
		List<Role> roleList = Lists.newArrayList();
		RoomVO beforeRoom = role.getRoleProxy().getRoomVO();
		if (beforeRoom != null){
			beforeRoom.setRoleId(0);
			beforeRoom.update();
		}

		long oldRoleId = room.getRoleId();
		if (oldRoleId != 0L){
			Role oldRole = RoleCache.me().getById(oldRoleId);
			oldRole.getRoleProxy().setRoomVO(null);
			roleList.add(oldRole);
			RoleManager.me().calcEffect(oldRole);
		}

		room.setRoleId(role.getId());
		room.update();
		role.getRoleProxy().setRoomVO(room);
		RoleManager.me().calcEffect(role);
		roleList.add(role);
		return roleList;
	}

	/**
	 * 解锁房间
	 * */
	public static void unlockRoom(Player player, RoomCfg roomCfg){
		ItemManager.me().costGoodsByCid(player, roomCfg.getUnlockCost(),LogDsp.newBuilder(GoodsDsp.UNLOCK_ROOM),ItemList.newBuilder());
		ItemManager.me().addGoodsAndPush(player,null,null, MapUtil.of(roomCfg.getId(),1),LogDsp.newBuilder(GoodsDsp.UNLOCK_ROOM));
	}



	/**
	 * 计算房间影响
	 * */
	private void calcEffect(Role role){
		Map<Integer,Integer> effectMap = Maps.newHashMap();

		//房间效果
		CommonUtil.changeMap(effectMap,getRoomEffect(role));

		role.getRoleProxy().setEffectMap(effectMap);
	}

	/**
	 * 获取房间影响
	 * */
	private Map<Integer,Integer> getRoomEffect(Role role){
		RoomCfg roomCfg = role.getRoleProxy().getRoomVO().getCfg();
		Map<Integer,Integer> result = Maps.newHashMap();
		for (Object o : roomCfg.getEffect()) {
			Map map = (Map) o;
			//如果配置了roleId，就只对该role起作用，没有则对所有role起作用
			int roleId = ToolMap.getInt("roleId",map,0);
			if (roleId != 0 && roleId == role.getCid() || roleId == 0){
				result.put((int)map.get("type"), (int)map.get("value"));
			}
		}
		return result;
	}

	public void resetCityTriggerCountByLogin(Player player){
		PlayerData pd = player.getPlayerDatasFkPlayerId();
		PlayerDataVO.DiscreteVO discreteVO = pd.getPlayerDataProxy().getDiscreteVO();
		if (!TimeUtil.isSameDay(System.currentTimeMillis(),discreteVO.getLastResetCityDatingCountTime().getTime())){
			resetCityTriggerCount(player,new Date());
		}
	}

	public void resetCityTriggerCount(Player player, Date now){
		List<Role> roleList = player.getRolesFkPlayerId();

		roleList.forEach(role->{
			if (role.getTodayCityDatingCount() > 0){
				role.setTodayCityDatingCount(0);
				role.update();
			}
		});
		PlayerData pd = player.getPlayerDatasFkPlayerId();
		PlayerDataVO.DiscreteVO discreteVO = pd.getPlayerDataProxy().getDiscreteVO();
		discreteVO.setLastResetCityDatingCountTime(now);
	}
}
